<?php

namespace api\modules\v1\forms\base;

use common\models\base\Department;
use common\models\member\Attr;
use services\base\DepartmentService;
use services\member\MemberDepartmentService;
use services\member\MemberService;
use Yii;
use yii\base\Model;


class DepartmentForm extends Model
{
    /**
     * @var int $id ID
     * @var int $pid 父部门ID
     * @var int $department_name 部门名称
     * @var int $data_level 数据权限
     * @var array $select_role_ids 筛选范围角色IDs
     * @var int $default_role_id 默认角色ID
     * @var array $leader_member_ids 部门负责人IDs【编辑存在】
     * @var string $sort 排序
     * @var int $status 状态
     */
    public $id;
    public $pid;
    public $department_name;
    public $data_level;
    public $select_role_ids;
    public $default_role_id;
    public $leader_member_ids;
    public $sort;
    public $status;
    public $after_id;

    /**
     * @var Department $_department
     * @var Department $_pDepartment
     * @var Department $_afterDepartment
     * @var Department[] $_chilDepartmentList
     * @var Attr[] $_leaderMemberAttrList
     * @var array $_selectRoleList
     * @var array $_selectRoleIdsFormat
     * @var array $_leaderMemberIdsFormat
     */
    protected $_department;
    protected $_pDepartment;
    protected $_afterDepartment;
    protected $_chilDepartmentList;
    protected $_leaderMemberAttrList;
    protected $_selectRoleList;
    protected $_selectRoleIdsFormat;
    protected $_leaderMemberIdsFormat;


    public function rules()
    {
        return [
            // 参数验证
            [['department_name', 'data_level', 'select_role_ids', 'default_role_id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['id', 'department_name', 'data_level', 'select_role_ids', 'default_role_id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id', 'pid', 'after_id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],

            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['edit', 'move', 'delete']],
            [['pid'], 'checkPid', 'skipOnEmpty' => false, 'on' => ['create', 'move']],
            [['department_name'], 'checkDepartmentName', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['data_level'], 'checkDataLevel', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['select_role_ids'], 'checkSelectRoleIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['default_role_id'], 'checkDefaultRoleIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['leader_member_ids'], 'checkLeaderMemberIds', 'skipOnEmpty' => false, 'on' => ['edit']],
            [['next_id'], 'checkAfterId', 'skipOnEmpty' => false, 'on' => ['move']],
//            [['sort'], 'checkSort', 'skipOnEmpty' => true, 'on' => ['create', 'edit']],
//            [['status'], 'checkStatus', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = ['pid', 'department_name', 'data_level', 'select_role_ids', 'default_role_id'];

        // 编辑
        $scenarios['edit'] = ['id', 'department_name', 'data_level', 'select_role_ids', 'default_role_id', 'leader_member_ids'];

        // 移动
        $scenarios['move'] = ['id', 'pid', 'after_id'];

        // 删除
        $scenarios['delete'] = ['id'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => '部门ID',
            'pid' => '父部门ID',
            'department_name' => '部门名称',
            'data_level' => '数据权限',
            'select_role_ids' => '角色',
            'default_role_id' => '默认角色',
            'leader_member_ids' => '部门负责人',
            'sort' => '排序',
            'status' => '状态',
        ];
    }

    /**
     * 检验部门ID
     * @param $attribute
     * @return void
     */
    public function checkId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $department = $this->getDepartment();
        if (!$department) {
            $this->addError($attribute, '部门不存在');
            return;
        }

        if ($department->status == Department::STATUS_DELETE) {
            $this->addError($attribute, '部门已删除');
            return;
        }

        if ($this->getScenario() == 'delete') {
            if (DepartmentService::hasChildDepartment($department->id)) {
                $this->addError($attribute, '存在子部门，无法删除');
                return;
            }
        }
    }

    /**
     * 检验部门PID
     * @param $attribute
     * @return void
     */
    public function checkPid($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $pDepartment = $this->getParentDepartment();
        if ($pDepartment) {
            if ($pDepartment->status == Department::STATUS_DELETE) {
                $this->addError($attribute, '父部门已删除');
                return;
            }
            if ($this->getScenario() == 'move') {
                $department = $this->getDepartment();
                if ($pDepartment->level > $department->level && strpos($pDepartment->tree_id, $department->tree_id) !== false) {
                    $this->addError($attribute, '父部门不能为当前部门子部门');
                    return;
                }
                $maxLevel = 3;
                if ($pDepartment->level > $maxLevel - 1) {
                    $this->addError($attribute, '父级部门最多两级');
                    return;
                }
                $diffLevel = DepartmentService::getDepartmentDiffLevelNum($department->id);
                if ($pDepartment->level + $diffLevel + 1 > $maxLevel) {
                    $this->addError($attribute, '部门最多三级');
                    return;
                }
            }
        }
    }

    /**
     * 校验部门名称
     * @param $attribute
     * @return void
     */
    public function checkDepartmentName($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $len = mb_strlen($this->department_name);
        if ($len > 20) {
            $this->addError($attribute, '部门名称过长，最多20个字');
            return;
        }

        // 是否检验
        $isCheck = true;
        if ($this->getScenario() == 'edit') {
            $department = $this->getDepartment();
            // 部门参数未改变【跳过】
            if ($department->department_name == $this->department_name) {
                $isCheck = false;
            }
        }
        if ($isCheck) {
            $one = Department::findOne([
                'department_name' => $this->department_name,
                'status' => [Department::STATUS_INVALID, Department::STATUS_ENABLE],
            ]);
            if ($one) {
                $this->addError($attribute, "部门【{$this->department_name}】已存在");
                return;
            }
        }
    }

    /**
     * 校验数据权限
     * @param $attribute
     * @return void
     */
    public function checkDataLevel($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        $dataLevelCondition = DepartmentService::getDataLevelCondition();
        if (!in_array($this->data_level, array_column($dataLevelCondition, 'value'))) {
            $this->addError($attribute, "非法数据权限参数");
            return;
        }
    }

    /**
     * 校验角色参数
     * @param $attribute
     * @return void
     */
    public function checkSelectRoleIds($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $selectRoleList = $this->getSelectRoleList();
        if (array_diff($this->getSelectRoleIds(), array_column($selectRoleList, 'value'))) {
            $this->addError($attribute, "角色数据异常【角色超出筛选范围】");
            return;
        }
    }

    /**
     * 校验默认角色参数
     * @param $attribute
     * @return void
     */
    public function checkDefaultRoleIds($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if (in_array($this->default_role_id, $this->getSelectRoleIds()) === false) {
            $this->addError($attribute, "默认角色非角色范围内数据");
            return;
        }
    }

    /**
     * 校验部门负责人
     * @param $attribute
     * @return void
     */
    public function checkLeaderMemberIds($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->data_level == Department::DATA_LEVEL_SELF) {
            $department = $this->getDepartment();
            $leaderMemberList = MemberService::getEditCondition(MemberDepartmentService::getMemberIdsByDepartmentId($department->id), $department->leader_member_ids);
            if (array_diff($this->getLeaderMemberIds(), array_column($leaderMemberList, 'value'))) {
                $this->addError($attribute, "部门负责人参数异常，存在非当前部门人员");
                return;
            }
        }
    }

    /**
     * 校验移动之后ID
     * @param $attribute
     * @return void
     */
    public function checkAfterId($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        $afterDepartment = $this->getAfterDepartment();
        if (empty($afterDepartment)) {
//            $this->addError($attribute, '部门不存在');
            return;
        }

        if ($afterDepartment->status == Department::STATUS_DELETE) {
            $this->addError($attribute, '部门已删除');
            return;
        }

        $pDepartment = $this->getParentDepartment();
        $pid = $pDepartment->id ?? 0;
        if ($afterDepartment->pid != $pid) {
            $this->addError($attribute, '转移部门和之后部门非同一个父部门');
            return;
        }
    }

    /**
     * 校验部门排序
     * @param $attribute
     * @return void
     */
    public function checkSort($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if ($this->sort < 0) {
            $this->addError($attribute, '排序值不能小于0');
            return;
        }
    }

    /**
     * 校验部门状态
     * @param $attribute
     * @return void
     */
    public function checkStatus($attribute): void
    {
        if ($this->hasErrors()) {
            return;
        }

        if (!in_array($this->status, [Department::STATUS_INVALID, Department::STATUS_ENABLE])) {
            $this->addError($attribute, "非法状态");
            return;
        }
    }

    /**
     * 获取部门信息
     * @return Department|null
     */
    public function getDepartment(): ?Department
    {
        if (empty($this->_department)) {
            $this->_department = Department::findOne($this->id);
        }

        return $this->_department;
    }

    /**
     * 获取部门信息
     * @return Department|null
     */
    public function getParentDepartment(): ?Department
    {
        if (empty($this->_pDepartment)) {
            $this->_pDepartment = Department::findOne($this->pid);
        }

        return $this->_pDepartment;
    }

    /**
     * 获取部门信息
     * @return Department|null
     */
    public function getAfterDepartment(): ?Department
    {
        if (empty($this->_afterDepartment)) {
            $this->_afterDepartment = Department::findOne($this->after_id);
        }

        return $this->_afterDepartment;
    }

    /**
     * 获取筛选角色信息
     * @return array
     */
    public function getSelectRoleList(): array
    {
        if (is_null($this->_selectRoleList)) {
            $department = $this->getScenario() == 'create' ? $this->getParentDepartment() : Department::findOne($this->getDepartment()->pid);
            $this->_selectRoleList = DepartmentService::getSelectRoleCondition($department);
        }

        return $this->_selectRoleList;
    }

    public function getSelectRoleIds(): array
    {
        if (is_null($this->_selectRoleIdsFormat)) {
            $this->_selectRoleIdsFormat = is_array($this->select_role_ids) ? $this->select_role_ids : [];
        }
        return $this->_selectRoleIdsFormat;
    }

    public function getLeaderMemberIds(): array
    {
        if (is_null($this->_leaderMemberIdsFormat)) {
            $this->_leaderMemberIdsFormat = is_array($this->leader_member_ids) && $this->data_level == Department::DATA_LEVEL_SELF ? $this->leader_member_ids : [];
        }
        return $this->_leaderMemberIdsFormat;
    }
}
